package three_shang.智能算法;

class AlgorithmPSO {
    double w; //惯性权重
    int n; // 粒子个数
    double[] x1;
    double[] x2;
    double[] v1;
    double[] v2;
    double c1 = 2;
    double c2 = 2;
    double[] pbest;
    double gbest;
    double vmax; // 速度最大值
    double xmax; // 位置最大值

    public AlgorithmPSO(int n, double w, double vmax, double xmax) {
        this.n = n;
        this.w = w;
        this.vmax = vmax;
        this.xmax = xmax;
        this.x1 = new double[n];
        this.x2 = new double[n];
        this.v1 = new double[n];
        this.v2 = new double[n];
        this.pbest = new double[n];
        for (int i = 0; i < n; i++) {
            pbest[i] = Double.MAX_VALUE;
        }
        gbest = Double.MAX_VALUE;
    }

    public static void main(String[] args) {
        AlgorithmPSO pso = new AlgorithmPSO(10, 0.7, 10.0, 10.0);
        pso.init(); //初始化每个解的位置和速度,随机生成
        pso.PSO(500);
    }

    public double fitnessFunction(double x1, double x2) {
        return x1 * x1 + x2 * x2;
    }

    public void init() {
        for (int i = 0; i < n; i++) {
            x1[i] = Math.random() * 2 * xmax - xmax;
            x2[i] = Math.random() * 2 * xmax - xmax;
            v1[i] = Math.random() * 2 * vmax - vmax;
            v2[i] = Math.random() * 2 * vmax - vmax;
        }
    }

    public void PSO(int iterations) {
        for (int it = 0; it < iterations; it++) {
            for (int i = 0; i < n; i++) {
                double currentFitness = fitnessFunction(x1[i], x2[i]);
                if (currentFitness < pbest[i]) {
                    pbest[i] = currentFitness;
                }
                if (currentFitness < gbest) {
                    gbest = currentFitness;
                }

                //0-1的随机数
                double r1 = Math.random();
                double r2 = Math.random();
                v1[i] = w * v1[i] + c1 * r1 * (pbest[i] - x1[i]) + c2 * r2 * (gbest - x1[i]);
                v2[i] = w * v2[i] + c1 * r1 * (pbest[i] - x2[i]) + c2 * r2 * (gbest - x2[i]);
                // 合法性调整 -> 确保v在-10到10之间
                v1[i] = Math.max(-vmax, Math.min(v1[i], vmax));
                v2[i] = Math.max(-vmax, Math.min(v2[i], vmax));
                //新的位置
                x1[i] += v1[i];
                x2[i] += v2[i];
                // 合法性调整 -> 确保x在-10到10之间
                x1[i] = Math.max(-xmax, Math.min(x1[i], xmax));
                x2[i] = Math.max(-xmax, Math.min(x2[i], xmax));

                //评估粒子的适应度函数值
                double afterFitness = fitnessFunction(x1[i], x2[i]);
                if (afterFitness < gbest) {
                    gbest = afterFitness;
                }

            }
            if (gbest == 0) {
                System.out.println("第 " + (it + 1) + " 次迭代，迭代中止！全局最优解 gbest = " + gbest);
                return;
            } else {
                System.out.println("第 " + (it + 1) + " 次迭代，全局最优解 gbest = " + gbest);
            }
        }
    }


}
